package temp.leetcode.editor.cn;

//给定两个整数数组 inorder 和 postorder ，其中 inorder 是二叉树的中序遍历， postorder 是同一棵树的后序遍历，请你构造并
//返回这颗 二叉树 。
//
//
//
// 示例 1:
//
//
//输入：inorder = [9,3,15,20,7], postorder = [9,15,7,20,3]
//输出：[3,9,20,null,null,15,7]
//
//
// 示例 2:
//
//
//输入：inorder = [-1], postorder = [-1]
//输出：[-1]
//
//
//
//
// 提示:
//
//
// 1 <= inorder.length <= 3000
// postorder.length == inorder.length
// -3000 <= inorder[i], postorder[i] <= 3000
// inorder 和 postorder 都由 不同 的值组成
// postorder 中每一个值都在 inorder 中
// inorder 保证是树的中序遍历
// postorder 保证是树的后序遍历
//
//
// Related Topics 树 数组 哈希表 分治 二叉树 👍 987 👎 0

import temp.二叉树.TreeNode;

import java.util.HashMap;

/**
 * 从中序与后序遍历序列构造二叉树
 *
 * @author saint
 */
class P106_ConstructBinaryTreeFromInorderAndPostorderTraversal{
    public static void main(String[] args) {
        Solution solution = new P106_ConstructBinaryTreeFromInorderAndPostorderTraversal().new Solution();
        int[] inorder = {9, 3, 15, 20, 7};
        int[] postorder = new int[]{9,15,7,20,3};
        solution.buildTree(inorder,postorder);
    }

    //leetcode submit region begin(Prohibit modification and deletion)
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    //优化，用map保存inorder中的下标和数值对应关系，便于查找
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        HashMap<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < inorder.length; i++) {
            map.put(inorder[i], i);
        }
        //后序的最后一个节点为根节点
        TreeNode root = new TreeNode(postorder[postorder.length - 1]);
        int inIndex = findNode(root.val, map);
        //切分
        root.left = buildChildTree(inorder, postorder, 0, inIndex - 1, 0, inIndex - 1, map);
        root.right = buildChildTree(inorder, postorder, inIndex + 1, inorder.length - 1, inIndex, postorder.length - 2, map);
        return root;
    }

    public TreeNode buildChildTree(int[] inorder, int[] postorder,
                                   int inLeft, int inRight, int postLeft, int postRight, HashMap<Integer, Integer> map) {
        if ((inLeft > inRight) || (postLeft > postRight)||(inLeft<0)||(postLeft<0)||(inRight>=inorder.length)||(postRight>=postorder.length)) {
            return null;
        }
        TreeNode node = new TreeNode(postorder[postRight]);
        int inIndex = findNode(node.val, map);
        node.left = buildChildTree(inorder, postorder, inLeft, inIndex - 1, postLeft, postLeft + inIndex - inLeft - 1, map);
        node.right = buildChildTree(inorder, postorder, inIndex + 1, inRight, postLeft + inIndex - inLeft, postRight - 1, map);
        return node;

    }

    public int findNode(int value, HashMap<Integer, Integer> map) {
        if (map.containsKey(value)) {
            return map.get(value);
        }
        return -1;
    }
}
//leetcode submit region end(Prohibit modification and deletion)

}
